home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1_3 / sys / vms / vmsmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-01  |  10.0 KB  |  420 lines

  1. /*    SCCS Id: @(#)vmsmain.c    3.1    93/06/27    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4. /* main.c - VMS NetHack */
  5.  
  6. #include "hack.h"
  7.  
  8. #include <signal.h>
  9.  
  10. volatile int exiting = 0;
  11.  
  12. static void NDECL(whoami);
  13. static void FDECL(process_options, (int, char **));
  14. static void NDECL(byebye);
  15. #ifndef SAVE_ON_FATAL_ERROR
  16. # ifndef __DECC
  17. extern void FDECL(VAXC$ESTABLISH, (int (*)(genericptr_t,genericptr_t)));
  18. # endif
  19. static int FDECL(vms_handler, (genericptr_t,genericptr_t));
  20. #include <ssdef.h>    /* system service status codes */
  21. #endif
  22.  
  23. int
  24. main(argc,argv)
  25. int argc;
  26. char *argv[];
  27. {
  28.     register int fd;
  29. #ifdef CHDIR
  30.     register char *dir;
  31. #endif
  32.  
  33. #ifdef SECURE    /* this should be the very first code executed */
  34.     privoff();
  35.     fflush((FILE *)0);    /* force stdio to init itself */
  36.     privon();
  37. #endif
  38.  
  39.     atexit(byebye);
  40.     hname = argv[0];
  41.     gethdate(hname);        /* find executable's creation date */
  42.     hname = basename(hname);    /* name used in 'usage' type messages */
  43.     hackpid = getpid();
  44.     (void) umask(0);
  45.  
  46.     choose_windows(DEFAULT_WINDOW_SYS);
  47.  
  48. #ifdef CHDIR            /* otherwise no chdir() */
  49.     /*
  50.      * See if we must change directory to the playground.
  51.      * (Perhaps hack is installed with privs and playground is
  52.      *  inaccessible for the player.)
  53.      * The logical name HACKDIR is overridden by a
  54.      *  -d command line option (must be the first option given)
  55.      */
  56.     dir = getenv("NETHACKDIR");
  57.     if (!dir) dir = getenv("HACKDIR");
  58. #endif
  59.     if(argc > 1) {
  60. #ifdef CHDIR
  61.         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
  62.         /* avoid matching "-dec" for DECgraphics; since the man page
  63.          * says -d directory, hope nobody's using -desomething_else
  64.          */
  65.         argc--;
  66.         argv++;
  67.         dir = argv[0]+2;
  68.         if(*dir == '=' || *dir == ':') dir++;
  69.         if(!*dir && argc > 1) {
  70.             argc--;
  71.             argv++;
  72.             dir = argv[0];
  73.         }
  74.         if(!*dir)
  75.             error("Flag -d must be followed by a directory name.");
  76.         } else
  77. #endif /* CHDIR */
  78.  
  79.     /*
  80.      * Now we know the directory containing 'record' and
  81.      * may do a prscore().
  82.      */
  83.         if (!strncmp(argv[1], "-s", 2)) {
  84. #ifdef CHDIR
  85.         chdirx(dir, FALSE);
  86. #endif
  87.         prscore(argc, argv);
  88.         exit(0);
  89.         }
  90.     }
  91.  
  92. #ifdef CHDIR
  93.     /* move to the playground directory; 'termcap' might be found there */
  94.     chdirx(dir, TRUE);
  95. #endif
  96.  
  97. #ifdef SECURE
  98.     /* disable installed privs while loading nethack.cnf and termcap,
  99.        and also while initializing terminal [$assign("TT:")]. */
  100.     privoff();
  101. #endif
  102.     initoptions();
  103.     init_nhwindows();
  104.     whoami();
  105. #ifdef SECURE
  106.     privon();
  107. #endif
  108.  
  109.     /*
  110.      * It seems you really want to play.
  111.      */
  112.     setrandom();
  113.     u.uhp = 1;    /* prevent RIP on early quits */
  114. #ifndef SAVE_ON_FATAL_ERROR
  115.     /* used to clear hangup stuff while still giving standard traceback */
  116.     VAXC$ESTABLISH(vms_handler);
  117. #endif
  118.     (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
  119.  
  120.     process_options(argc, argv);    /* command line options */
  121.  
  122. #ifdef WIZARD
  123.     if (wizard)
  124.         Strcpy(plname, "wizard");
  125.     else
  126. #endif
  127.     if(!*plname || !strncmp(plname, "games", 4))
  128.         askname();
  129.     plnamesuffix();        /* strip suffix from name; calls askname() */
  130.                 /* again if suffix was whole name */
  131.                 /* accepts any suffix */
  132. #ifdef WIZARD
  133.     if(!wizard) {
  134. #endif
  135.         /*
  136.          * check for multiple games under the same name
  137.          * (if !locknum) or check max nr of players (otherwise)
  138.          */
  139.         (void) signal(SIGQUIT,SIG_IGN);
  140.         (void) signal(SIGINT,SIG_IGN);
  141.         if(!locknum)
  142.             Sprintf(lock, "_%u%s", (unsigned)getuid(), plname);
  143.         getlock();
  144. #ifdef WIZARD
  145.     } else {
  146.         Sprintf(lock, "_%u%s", (unsigned)getuid(), plname);
  147.         getlock();
  148.     }
  149. #endif /* WIZARD */
  150.  
  151.     /*
  152.      * Initialisation of the boundaries of the mazes
  153.      * Both boundaries have to be even.
  154.      */
  155.  
  156.     x_maze_max = COLNO-1;
  157.     if (x_maze_max % 2)
  158.         x_maze_max--;
  159.     y_maze_max = ROWNO-1;
  160.     if (y_maze_max % 2)
  161.         y_maze_max--;
  162.  
  163.     /*
  164.      *  Initialize the vision system.  This must be before mklev() on a
  165.      *  new game or before a level restore on a saved game.
  166.      */
  167.     vision_init();
  168.  
  169.     display_gamewindows();
  170.  
  171.     set_savefile_name();
  172.     if((fd = open_savefile()) >= 0 &&
  173.        /* if not up-to-date, quietly unlink file via false condition */
  174.        (uptodate(fd) || delete_savefile())) {
  175. #ifdef WIZARD
  176.         /* Since wizard is actually flags.debug, restoring might
  177.          * overwrite it.
  178.          */
  179.         boolean remember_wiz_mode = wizard;
  180. #endif
  181.         (void) chmod(SAVEF,0);    /* disallow parallel restores */
  182.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  183. #ifdef NEWS
  184.         if(flags.news) {
  185.             display_file(NEWS, FALSE);
  186.             flags.news = FALSE; /* in case dorecover() fails */
  187.         }
  188. #endif
  189.         pline("Restoring save file...");
  190.         mark_synch();    /* flush output */
  191.         if(!dorecover(fd))
  192.             goto not_recovered;
  193. #ifdef WIZARD
  194.         if(!wizard && remember_wiz_mode) wizard = TRUE;
  195. #endif
  196.         pline("Hello %s, welcome back to NetHack!", plname);
  197.         check_special_room(FALSE);
  198. #ifdef EXPLORE_MODE
  199.         if (discover)
  200.             You("are in non-scoring discovery mode.");
  201. #endif
  202. #if defined(EXPLORE_MODE) || defined(WIZARD)
  203.         if (discover || wizard) {
  204.             if (yn("Do you want to keep the save file?") == 'n')
  205.                 (void) delete_savefile();
  206.             else
  207.                 (void) chmod(SAVEF,FCMASK); /* back to readable */
  208.         }
  209. #endif
  210.         flags.move = 0;
  211.     } else {
  212. not_recovered:
  213.         player_selection();
  214.         newgame();
  215.         /* give welcome message before pickup messages */
  216.         pline("Hello %s, welcome to NetHack!", plname);
  217. #ifdef EXPLORE_MODE
  218.         if (discover)
  219.             You("are in non-scoring discovery mode.");
  220. #endif
  221.         flags.move = 0;
  222.         set_wear();
  223.         pickup(1);
  224.     }
  225.  
  226.     flags.moonphase = phase_of_the_moon();
  227.     if(flags.moonphase == FULL_MOON) {
  228.         You("are lucky!  Full moon tonight.");
  229.         change_luck(1);
  230.     } else if(flags.moonphase == NEW_MOON) {
  231.         pline("Be careful!  New moon tonight.");
  232.     }
  233.     if ((flags.friday13 = friday_13th()) != 0) {
  234.         pline("Watch out!  Bad things can happen on Friday the 13th.");
  235.         change_luck(-1);
  236.     }
  237.  
  238.     initrack();
  239.  
  240.     moveloop();
  241.     return(0);
  242. }
  243.  
  244. static void
  245. process_options(argc, argv)
  246. int argc;
  247. char *argv[];
  248. {
  249.     /*
  250.      * Process options.
  251.      */
  252.     while(argc > 1 && argv[1][0] == '-'){
  253.         argv++;
  254.         argc--;
  255.         switch(argv[0][1]){
  256. #if defined(WIZARD) || defined(EXPLORE_MODE)
  257. # ifndef EXPLORE_MODE
  258.         case 'X':
  259.         case 'x':
  260. # endif
  261.         case 'D':
  262. # ifdef WIZARD
  263.             if(!strcmpi(getenv("USER"), WIZARD_NAME)) {
  264.                 wizard = TRUE;
  265.                 break;
  266.             }
  267.             /* otherwise fall thru to discover */
  268. # endif
  269. # ifdef EXPLORE_MODE
  270.         case 'X':
  271.         case 'x':
  272.             discover = TRUE;
  273. # endif
  274.             break;
  275. #endif
  276. #ifdef NEWS
  277.         case 'n':
  278.             flags.news = FALSE;
  279.             break;
  280. #endif
  281.         case 'u':
  282.             if(argv[0][2])
  283.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  284.             else if(argc > 1) {
  285.               argc--;
  286.               argv++;
  287.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  288.             } else
  289.                 raw_print("Player name expected after -u");
  290.             break;
  291.         case 'I':
  292.         case 'i':
  293.             if (!strncmpi(argv[0]+1, "IBM", 3))
  294.                 switch_graphics(IBM_GRAPHICS);
  295.             break;
  296.         /*  case 'D': */
  297.         case 'd':
  298.             if (!strncmpi(argv[0]+1, "DEC", 3))
  299.                 switch_graphics(DEC_GRAPHICS);
  300.             break;
  301.         default:
  302.             /* allow -T for Tourist, etc. */
  303.             (void) strncpy(pl_character, argv[0]+1,
  304.                 sizeof(pl_character)-1);
  305.  
  306.             /* raw_printf("Unknown option: %s", *argv); */
  307.         }
  308.     }
  309.  
  310.     if(argc > 1)
  311.         locknum = atoi(argv[1]);
  312. #ifdef MAX_NR_OF_PLAYERS
  313.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  314.         locknum = MAX_NR_OF_PLAYERS;
  315. #endif
  316. }
  317.  
  318. #ifdef CHDIR
  319. void
  320. chdirx(dir, wr)
  321. const char *dir;
  322. boolean wr;
  323. {
  324. # ifndef HACKDIR
  325.     static const char *defdir = ".";
  326. # else
  327.     static const char *defdir = HACKDIR;
  328.  
  329.     if(dir == NULL)
  330.         dir = defdir;
  331.     else if (wr && !same_dir(HACKDIR, dir))
  332.         /* If we're playing anywhere other than HACKDIR, turn off any
  333.            privs we may have been installed with. */
  334.         privoff();
  335. # endif
  336.  
  337.     if(dir && chdir(dir) < 0) {
  338.         perror(dir);
  339.         error("Cannot chdir to %s.", dir);
  340.     }
  341.  
  342.     /* warn the player if we can't write the record file */
  343.     if (wr) check_recordfile(dir);
  344.  
  345.     defdir = dir;
  346. }
  347. #endif /* CHDIR */
  348.  
  349. static void
  350. whoami()
  351. {
  352.     /*
  353.      * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
  354.      *            2. Use lowercase of $USER  (if 1. fails)
  355.      * The resulting name is overridden by command line options.
  356.      * If everything fails, or if the resulting name is some generic
  357.      * account like "games" then eventually we'll ask him.
  358.      * Note that we trust the user here; it is possible to play under
  359.      * somebody else's name.
  360.      */
  361.     register char *s;
  362.  
  363.     if (!*plname && (s = getenv("USER")))
  364.         (void) lcase(strncpy(plname, s, sizeof(plname)-1));
  365. }
  366.  
  367. static void
  368. byebye()
  369. {
  370.     /*    Different versions of both VAX C and GNU C use different return types
  371.     for signal functions.  Return type 'int' along with the explicit casts
  372.     below satisfy the most combinations of compiler vs <signal.h>.
  373.      */
  374.     int (*hup)();
  375. #ifdef SHELL
  376.     extern unsigned long dosh_pid, mail_pid;
  377.     extern unsigned long FDECL(SYS$DELPRC,(unsigned long *,const genericptr_t));
  378.  
  379.     /* clean up any subprocess we've spawned that may still be hanging around */
  380.     if (dosh_pid) (void) SYS$DELPRC(&dosh_pid, 0), dosh_pid = 0;
  381.     if (mail_pid) (void) SYS$DELPRC(&mail_pid, 0), mail_pid = 0;
  382. #endif
  383.  
  384.     /* SIGHUP doesn't seem to do anything on VMS, so we fudge it here... */
  385.     hup = (int(*)()) signal(SIGHUP, SIG_IGN);
  386.     if (!exiting++ && hup != (int(*)()) SIG_DFL && hup != (int(*)()) SIG_IGN)
  387.     (void) (*hup)();
  388.  
  389. #ifdef CHDIR
  390.     (void) chdir(getenv("PATH"));
  391. #endif
  392. }
  393.  
  394. #ifndef SAVE_ON_FATAL_ERROR
  395. /* Condition handler to prevent byebye's hangup simulation
  396.    from saving the game after a fatal error has occurred.  */
  397. static int            /* should be `unsigned long', but the -*/
  398. vms_handler(sigargs, mechargs)    /*+ prototype in <signal.h> is screwed */
  399. genericptr_t sigargs, mechargs;    /* [0] is argc, [1..argc] are the real args */
  400. {
  401.     extern boolean hu;        /* src/save.c */
  402.     unsigned long condition = ((unsigned long *)sigargs)[1];
  403.  
  404.     if (condition == SS$_ACCVIO        /* access violation */
  405.      || (condition >= SS$_ASTFLT && condition <= SS$_TBIT)
  406.      || (condition >= SS$_ARTRES && condition <= SS$_INHCHME)) {
  407.     hu = TRUE;    /* pretend that hangup has already been attempted */
  408. # if defined(WIZARD) && !defined(BETA)
  409.     if (wizard)
  410. # endif /*WIZARD && !BETA*/
  411. # if defined(WIZARD) ||  defined(BETA)
  412.         abort();    /* enter the debugger */
  413. # endif /*WIZARD || BETA*/
  414.     }
  415.     return SS$_RESIGNAL;
  416. }
  417. #endif
  418.  
  419. /*vmsmain.c*/
  420.